import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 一键整合指定js内容并覆盖至指定文件
 *
 * @author byhgz
 */
public class build {
    /**
     * 项目绝对路径
     */
    private static final String PROJECT_ABSOLUTE_PATH = System.getProperty("user.dir");

    /**
     * 排除文件数组
     */
    private static final JSONArray GITIGNORE = new JSONArray();


    public static void run() {
        List<JSONObject> initList = getInit();
        if (initList.size() == 0) {
            return;
        }
        System.out.println("当前项目有：");
        for (int i = 0; i < initList.size(); i++) {
            JSONObject jsonObject = initList.get(i);
            String name = jsonObject.get("name", String.class);
            if (name == null) {
                System.out.println("配置信息中项目格式不正确!请检查init.json文件！");
                return;
            }
            System.out.println(StrUtil.format("下标：{} 项目名：{}", i, name));
        }
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入你要进行打包的项目下标：");
        int inputIndex;
        try {
            inputIndex = Integer.parseInt(scanner.nextLine());
        } catch (Exception e) {
            System.out.println(StrUtil.format("请正确输入整数数值！错误信息：{}", e.getMessage()));
            scanner.close();
            return;
        }
        JSONObject itemInit;
        String itemName;
        try {
            itemInit = initList.get(inputIndex);
            itemName = itemInit.get("name", String.class);
            System.out.print("是要对该项目进行打包吗？" + itemName + "\n属于y打包，之外的不做任何处理");
        } catch (Exception e) {
            System.out.println(StrUtil.format("请正确输入下标！错误信息：{}", e.getMessage()));
            return;
        }
        String input = scanner.nextLine();
        scanner.close();
        if (!"y".equals(input)) {
            return;
        }
        getItemInit(itemInit);
        List<String> splicingSequencelist = getSplicingSequencelist(itemName, itemInit.get("res_path", String.class));
        if (splicingSequencelist == null) {
            System.out.println(StrUtil.format("未获取到项目{} 的本地开发合并路径文件！", itemName));
            return;
        }
        System.out.println("输入了y，开始打包...");
        JSONArray gitignoreList = itemInit.get("gitignore", JSONArray.class);
        if (gitignoreList != null) {
            GITIGNORE.addAll(gitignoreList);
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (String v : splicingSequencelist) {
            String read = FileUtil.readUtf8String(v);
            if (v.lastIndexOf("\\metaData.js") != -1) {//排除针对于头部描述信息的格式化处理
                stringBuilder.append(read).append("\n");
                continue;
            }
            if (itemInit.get("isFormatting", boolean.class)) {
                read = read.trim().replace("  ", "");//对js代码文件去除不必要的空格，如果不需要请注释
            }
            stringBuilder.append(read).append("\n");
        }
        String content = String.valueOf(stringBuilder).trim();
        File file;
        try {
            file = FileUtil.writeUtf8String(content, itemInit.get("to_path", String.class));
        } catch (IORuntimeException e) {
            System.out.println(StrUtil.format("保存打包内容时出错！\n打包路径：\n{}\n错误信息：{}", itemInit, e.getMessage()));
            return;
        }
        System.out.println("================打包成功！======================");
        System.out.println("已整合js代码保存在" + file);
        System.out.println("================打包成功！======================");
    }

    /**
     * 排除的文件
     *
     * @param path 文件路径
     * @return 是否排除
     */
    private static boolean excludeFileName(String path) {
        boolean temp = false;
        if (GITIGNORE.size() == 0) {
            return false;
        }
        String fIleName = FileUtil.getName(path);
        for (Object o : GITIGNORE) {
            if (!fIleName.equals(o)) {
                continue;
            }
            temp = true;
            break;
        }
        return temp;
    }

    /**
     * 获取所有配置信息
     */
    private static List<JSONObject> getInit() {
        List<JSONObject> read = new ArrayList<>(0);
        String initPath = StrUtil.format("{}\\res\\init.json", PROJECT_ABSOLUTE_PATH);
        try {
            JSONArray tempArray = JSONUtil.readJSONArray(new File(initPath), StandardCharsets.UTF_8);
            for (Object v : tempArray) {
                read.add((JSONObject) v);
            }
        } catch (IORuntimeException e) {
            System.out.println(StrUtil.format("获取配置信息出错！，可能是没配置init.json文件，\n int.json路径：{}\n错误信息：{}", initPath, e.getMessage()));
        }
        return read;
    }


    /**
     * 获取指定项目的init配置信息
     */
    private static void getItemInit(JSONObject read) {
        if (read.size() == 0) {
            read.set("isFormatting", false);
            String defToPath = PROJECT_ABSOLUTE_PATH + "\res\\res.json";
            read.set("to_path", defToPath);
            read.set("gitignore", new JSONArray(0));
            System.out.println(StrUtil.format("获取配置信息出错！，可能是没配置init.json文件，故使用默认配置信息:\n{}", JSONUtil.toJsonPrettyStr(read)));
            return;
        }
        System.out.println("====获取配置init.json信息成功。配置信息为：====\n" + JSONUtil.toJsonPrettyStr(read));
    }

    /**
     * 获取拼接顺序
     */
    private static List<String> getSplicingSequencelist(String name, String path) {
        List<String> list = new ArrayList<>(0);
        List<String> lines;
        try {
            lines = FileUtil.readUtf8Lines((path));
        } catch (IORuntimeException e) {
            System.out.println(StrUtil.format("读取失败或未配置本地开发文件路径顺序！项目名：{}，错误信息：{}", name, e.getMessage()));
            return null;
        }
        for (String linePath : lines) {
            if (linePath.trim().isEmpty()) {
                continue;
            }
            String tempPath = linePath.replaceAll("// @require.*.file:///", "");
            if (excludeFileName(tempPath)) {
                continue;
            }
            list.add(tempPath);
        }
        return list;
    }

}